//-----------------------------------------------------------------------

// <copyright file="ComboBoxFieldDefinition.cs" company="Jamie Knight">

// Copyright (c) Jamie Knight. All rights reserved.

// </copyright>

//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using Humanizer;

namespace DevKnightlie.WPF.AutoForm.FieldDefinitions
{

    /// <summary>
    /// Converter for converting enums to strings
    /// </summary>
    /// <remarks>Thanks to user RSmaller at StackOverflow
    /// http://stackoverflow.com/questions/15567913/wpf-how-to-bind-an-enum-with-descriptions-to-a-combobox
    /// and the excellent http://humanizr.net Humanizer library
    /// </remarks>
    public class EnumDescriptionConverter : IValueConverter
    {
        private string GetEnumDescription(Enum enumObj)
        {
            FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString());

            object[] attribArray = fieldInfo.GetCustomAttributes(false);

            if (attribArray.Length == 0)
            {
                return enumObj.ToString().Humanize();
            }
            else
            {
                DescriptionAttribute attrib = attribArray[0] as DescriptionAttribute;
                return attrib.Description;
            }
        }

        object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Enum myEnum = (Enum)value;
            string description = GetEnumDescription(myEnum);
            return description;
        }

        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            String s = (value as String).Dehumanize();
            String[] arr = Enum.GetNames(targetType);
            Enum e= null;
            for (int loop = 0; loop < arr.Length; loop++)
            {
                if (arr[loop].Equals(s)) {
                    e = (Enum.GetValues(targetType).GetValue(loop) as Enum);
                    break;
                }
            }            
            return e;
        }
    }


    /// <summary>
    /// Field definition class for a combobox
    /// </summary>
    public class ComboBoxFieldDefinition : BaseFieldDefinition
    {
        #region Private Fields

        private List<object> _items = new List<object>();
        private string _itemsPropertyName;

        #endregion

        #region Properties

        /// <summary>
        /// Sets or returns the list of items to display in the combo box
        /// </summary>
        public List<Object> Items
        {
            get
            {
                return _items;
            }
            set
            {
                _items = value;
            }
        }


        /// <summary>
        /// Sets or returns a property name which holds the list of items to display
        /// </summary>
        public String ItemsPropertyName
        {
            get { return _itemsPropertyName; }
            set { _itemsPropertyName = value; }
        }

        #endregion

        #region Methods

        public override void BuildInputControl()
        {
            ComboBox comboBox = new ComboBox()
            {
                VerticalContentAlignment = System.Windows.VerticalAlignment.Center,
                HorizontalContentAlignment = System.Windows.HorizontalAlignment.Left
            };
            if (PropertyInfo != null && PropertyInfo.PropertyType.IsEnum)
            {
                // The property is an enumeration, so build the Items list automatically
                string[] enumStrings = Enum.GetNames(PropertyInfo.PropertyType);
                List<String> stringList = new List<string>(enumStrings.Length);
                stringList.AddRange(enumStrings.Select(enumString => enumString.Humanize()));
                comboBox.ItemsSource = stringList;
            }
            else if (String.IsNullOrWhiteSpace(ItemsPropertyName))
            {
                comboBox.ItemsSource = Items;
            }
            else
            {
                Binding itemsBinding = new Binding(ItemsPropertyName);
                BindingOperations.SetBinding(comboBox, ItemsControl.ItemsSourceProperty, itemsBinding);
            }
            Binding comboBoxBinding = new Binding(PropertyName);
            if (PropertyInfo != null && PropertyInfo.PropertyType.IsEnum)
            {
                comboBoxBinding.Converter = new EnumDescriptionConverter();
            }
            BindingOperations.SetBinding(comboBox, Selector.SelectedValueProperty, comboBoxBinding);
            SetupEnabledBinding(comboBox);
            ContainerControl = InputControl = comboBox;
        }


        #endregion

        #region Constructor

        public ComboBoxFieldDefinition()
        {

        }

        #endregion

    }
}
